//----------------------------------*-C++-*----------------------------------//
/*
 * \file   SlabtranInput.hh
 * \author Jeremy Roberts
 * \date   04/10/2011
 * \brief  A class for handling input for SLABTRAN.
 * \note   Copyright (C) 2011 Jeremy Roberts
 */ 
//---------------------------------------------------------------------------//
// $Rev::                                               $:Rev of last commit
// $Author::                                            $:Author of last commit
// $Date::                                              $:Date of last commit
//---------------------------------------------------------------------------//

#ifndef GLOBALINPUT_HH
#define GLOBALINPUT_HH

#include <iostream>
#include <fstream>
#include <vector>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/relaxng.h>
#include "../utilities/InputXML.hh"
#include "../utilities/SP.hh"
#include "tran/SlabtranElement.hh"
#include "tran/Definitions.hh"

namespace slabtran
{

//===========================================================================//
/*
 * \class SlabtranInput
 * \brief This class handles all input for SLABTRAN.
 *
 *  This class used the libxml2 library to parse xml inputs.  Some of the code
 *  is very much inspired by K. Huff's cyclus input processing routines.
 *
 *  \todo Input handling is very much in flux, especially after getting to
 *        know Denovo and seeing a much more flexible way of doing it.  I
 *        think the best approach is to have two input types, one based on
 *        xml as done now and one based on a silo database (generated e.g.
 *        by python).  Basically, in either case, the underlying parser
 *        will store exactly that information needed to create the various
 *        objects (like Mesh and Materials, etc.).  This would let allow a
 *        very superficial python interface be put in place (potentially
 *        for incremental additions as necessary).  Basically, the hierarchy
 *        would be Input.hh <-- InputSilo.hh or InputXML
 *
 *
 *
 */ 
//===========================================================================//

class SlabtranInput : public InputXML
{

  public:

  	//@{
  	//! Useful typedefs for classes that use SlabtranElement
  	//@{
  	typedef util::SP<SlabtranInput>		SP_input;
  	typedef SlabtranElement::SP_element SP_element;
  	typedef double scalar;
  	typedef int    integer;
  	//@}

  private:

        // ------------------------------------------------------------------
        // CONTROL
        // ------------------------------------------------------------------

        /// \brief problen name
		string d_name;

        /// \brief problem type (0 for fixed source, 1 for eigenvalue)        
		integer d_ptype;

		/// \brief angular flux store switch
		bool d_store_psi;

        /// \brief solver type (0 for diffusion, 1 for discrete ordinates)   
		integer d_stype;

        /// \brief spatial dimension
		integer d_spacedim;

        /// \brief discrete ordinates quadrature order (i.e. "N" is "SN")        
		integer d_quadord;
 
        /// \brief \f$ k_{e\!f\!f} \f$ iteration relative precision (only ptype = 1)
        scalar  d_epsk;

        /// \brief flux iteration relative precision (or source precision, ptype = 1)
        scalar  d_epss;

        /// \brief maximum number of outer iterations
        scalar  d_maxit;

        /// \brief initial guess for \f$ k_{e\!f\!f} \f$
        scalar  d_keff;

        /// \brief number of elements 
        integer d_numel;

        /// \brief angular expansion order (*different* than quadord)
        integer d_angord;

        // ------------------------------------------------------------------
        // OUTPUT (NOT FULLY KNOWN YET)
        // ------------------------------------------------------------------

        /// \brief should I print? 1=yes, 0=no        
        integer  d_printout;

        /// \brief where should I print?        
        string   d_outfile;

        /// \brief should i plot? 1=yes, 0=no        
        integer  d_plotout;

        /// \brief where should I print?
        string   d_fluxfile;

        // ------------------------------------------------------------------
        // MATERIAL DATA
        // ------------------------------------------------------------------

		// note: a good, flexible idea would be to allow a flag for the xsec
        // data to be held in another file (library) while leaving open the 
        // ability to enter them as done currently for small, simple sets

		/// \brief info about the data
		string info;

        /// \brief number of energy groups for given data
        integer  numg;

        /// \brief number of materials for given data
        integer  numm;

        //  \todo It is worth thinking about making a distinction between
        //        legendre order for scattering and legendre order for
        //        flux expansion.  Of course the latter must be at least
        //        as great as the former, but there might be cases (e.g.
        //        DGM) where we want to represent psi via moments so as
        //        to cut down storage.

        /// \brief legendre order.
        int d_legendre_order;

        /// \brief legendre order for scattering.
        int d_legendre_order_scattering;

        /// \brief material/group total cross-section [][]
        vector<string>  matname;

        /// \brief material/group total cross-section [][]
        vector<vector<scalar> >  st;

        /// \brief material/group diffusion coefficient [][]
        vector<vector<scalar> >  dc;

        /// \brief material/group removal cross-section [][]
        vector<vector<scalar> >  sr;

        /// \brief material/group absorption cross-section [][]
        vector<vector<scalar> >  ab;

        /// \brief material/group $\nu \Sigma_f$ [][]
        vector<vector<scalar> >  ns;

        /// \brief material/group chi-spectrum [][]
        vector<vector<scalar> >  chi;

        /// \brief material/group scattering cross-section [][][]
        vector<vector<vector<scalar> > > ss;

        // ------------------------------------------------------------------
        // ELEMENTS (i.e. INDIVIDUAL PROBLEMS)
        // ------------------------------------------------------------------

        /// \brief elements of the problem
        vector<SlabtranElement> elements;

   public:

        SlabtranInput(string S);

		~SlabtranInput();

        void echoInput();

		string name(){ return d_name; };

		integer ptype(){ return d_ptype; };

		integer stype(){ return d_stype; };

		bool store_psi(){ return d_store_psi; };

		integer number_groups(){ return numg; };

		integer spacedim() const { return d_spacedim; };

		integer quadord(){ return d_quadord; };

        scalar  epsk(){ return d_epsk; };

        scalar  epss(){ return d_epss; };

        scalar  maxit(){ return d_maxit; };

        scalar  keff(){ return d_keff; };

        integer numel(){ return d_numel; };

        integer angord(){ return d_angord; };

        int legendre_order(){ return d_legendre_order; };


		//---------------------------------------------------------------------
		// Access element contents

        // Return my identification
        int id( int e );

        // Return my description
        string desc( int e );

        // Return source
        double src( int e, int i, int j, int k, int g);

        // Return coarse mesh edges in in x/y/z
        int ncm( int e, int dim);

        // Return coarse mesh count in in x/y/z
        double cm( int e, int xyz, int dim);

        // Return fine mesh count in x/y/z
        int nfm( int e, int xyz, int dim);

        // Return material id in x/y/z
        int mt( int e, int i, int j = 0, int k = 0);

        // Return an element
        SP_element element( int e );

	private: // should be more private things... eventually all the data above will be, and access will be from the return functions

        bool processFile();

		void sayHello();

		void checkElIdx( int i );

};

} // end namespace slabtran

#endif // GLOBALINPUT_HH

//---------------------------------------------------------------------------//
//                 end of SlabtranInput.hh
//---------------------------------------------------------------------------//

